// WGS84：为一种大地坐标系，也是目前广泛使用的GPS全球卫星定位系统使用的坐标系。
// GCJ02：又称火星坐标系，是由中国国家测绘局制订的地理信息系统的坐标系统。由WGS84坐标系经加密后的坐标系。
// BD09：为百度坐标系，在GCJ02坐标系基础上再次加密。其中bd09ll表示百度经纬度坐标，bd09mc表示百度墨卡托米制坐标。

const x_PI = (3.14159265358979324 * 3000.0) / 180.0
const PI = 3.1415926535897932384626
const a = 6378245.0
const ee = 0.00669342162296594323

/** 将 WGS84大地坐标系 转换成 百度坐标系 */
export function toBDMapPoint(point: any) {
  //先转成火星坐标系 ，WGS84转GCj02
  let x = point.lng ? point.lng : point.x
  let y = point.lat ? point.lat : point.y
  if (!x && !y) {
    x = point.longitude
    y = point.latitude
  }
  x = parseFloat(x)
  y = parseFloat(y)
  if (135.05 > x && x > 73.67 && 53.55 > y && y > 3.87) {
    //先转成火星坐标系 ，WGS84转GCj02
    const valueObj = { lng: x, lat: y }
    const gcj02Point = wgs84ToGCJ02(valueObj.lng, valueObj.lat)
    const point3 = {
      lng: gcj02Point[0],
      lat: gcj02Point[1]
    }
    //再由火星坐标系转成百度坐标系 GCj02转成(BD-09)
    const baiduPoint = gcj02ToBd09(point3.lng, point3.lat)
    point.lng = baiduPoint[0]
    point.lat = baiduPoint[1]
    // if (point.uploadDate) {
    //   point.loc_time = new Date(point.uploadDate).getTime()
    // }
    return point
  } else {
    return false
  }
}

/** 将 WGS84大地坐标系数组 转换成 百度坐标系数组 */
export function toBDMapPointArr(points: any[]) {
  //1.先过滤坐标为0.0，null，undefined，''等情况的数据
  const resultArr = []

  for (let i = 0; i < points.length; i++) {
    let x = points[i].x ? points[i].x : points[i].lng
    let y = points[i].y ? points[i].y : points[i].lat
    if (!x && !y) {
      x = points[i].longitude
      y = points[i].latitude
    }
    x = parseFloat(x)
    y = parseFloat(y)

    if (135.05 > x && x > 73.67 && 53.55 > y && y > 3.87) {
      //先转成火星坐标系 ，WGS84转GCj02
      const valueObj = { lng: x, lat: y }
      const gcj02Point = wgs84ToGCJ02(valueObj.lng, valueObj.lat)
      const point3 = {
        lng: gcj02Point[0],
        lat: gcj02Point[1]
      }
      //再由火星坐标系转成百度坐标系 GCj02转成(BD09)
      const baiduPoint = gcj02ToBd09(point3.lng, point3.lat)

      points[i].lng = baiduPoint[0]
      points[i].lat = baiduPoint[1]
      // if (points[i].uploadDate) {
      //   const dateStr = points[i].uploadDate.split('-').join('/')
      //   points[i].loc_time = new Date(dateStr).getTime()
      // }
      resultArr.push(points[i])
    }
  }
  return resultArr
}

/**
 * WGS84大地坐标系 转 GCJ02火星坐标系
 */
function wgs84ToGCJ02(lng: string | number, lat: string | number) {
  const longitude = +lng //经度
  const latitude = +lat // 维度
  if (outOfChina(longitude, latitude)) {
    return [longitude, latitude]
  } else {
    let dLat = transFormLat(longitude - 105.0, latitude - 35.0)
    let dLng = transFormLng(longitude - 105.0, latitude - 35.0)
    const radLat = (latitude / 180.0) * PI
    let magic = Math.sin(radLat)
    magic = 1 - ee * magic * magic
    const sqrtMagic = Math.sqrt(magic)
    dLat = (dLat * 180.0) / (((a * (1 - ee)) / (magic * sqrtMagic)) * PI)
    dLng = (dLng * 180.0) / ((a / sqrtMagic) * Math.cos(radLat) * PI)
    const mgLat = latitude + dLat
    const mgLng = longitude + dLng
    return [mgLng, mgLat]
  }
}

/**
 * 火星坐标系 (GCJ02) 与百度坐标系 (BD09) 的转换
 */
function gcj02ToBd09(lng: string | number, lat: string | number) {
  const longitude = +lng //经度
  const latitude = +lat // 维度
  const z = Math.sqrt(longitude * longitude + latitude * latitude) + 0.00002 * Math.sin(latitude * x_PI)
  const theta = Math.atan2(latitude, longitude) + 0.000003 * Math.cos(longitude * x_PI)
  const bdLng = z * Math.cos(theta) + 0.0065
  const bdLat = z * Math.sin(theta) + 0.006
  return [bdLng, bdLat]
}

/**
 * 判断是否在国内，不在国内则不做偏移
 */
function outOfChina(lng: number, lat: number) {
  // 纬度3.86~53.55,经度73.66~135.05
  return !(lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55)
}

function transFormLat(lng: number, lat: number) {
  let ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng))
  ret += ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0) / 3.0
  ret += ((20.0 * Math.sin(lat * PI) + 40.0 * Math.sin((lat / 3.0) * PI)) * 2.0) / 3.0
  ret += ((160.0 * Math.sin((lat / 12.0) * PI) + 320 * Math.sin((lat * PI) / 30.0)) * 2.0) / 3.0
  return ret
}

function transFormLng(lng: number, lat: number) {
  let ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng))
  ret += ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0) / 3.0
  ret += ((20.0 * Math.sin(lng * PI) + 40.0 * Math.sin((lng / 3.0) * PI)) * 2.0) / 3.0
  ret += ((150.0 * Math.sin((lng / 12.0) * PI) + 300.0 * Math.sin((lng / 30.0) * PI)) * 2.0) / 3.0
  return ret
}
